// ----------------------------------------------------------------------------
/**
 * @file    Server.h
 *
 * @brief   Header file for Server.cpp
 *
 * Accepts connections from IM client applications and manages friends, and passes the messages on.
 *
 * @author  Siddharth Sathyam <ssathy2@gmail.com>
 * @author  Alan Ruvalcaba <aruval3@gmail.com>
 * @author  Patrick LaMontagna <plamontagna@gmail.com
 *
 * @version 1.0
 *
 * @date    November 24th, 2011
 *
 */
// ----------------------------------------------------------------------------

#ifndef SERVER_H
#define SERVER_H

#include <QDataStream>
#include <QDebug>
#include <QHash>
#include <QStringList>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTime>
#include "clientinformation.h"

/**
 * @class   Server
 *
 * @brief   Server helper methods
 *
 * Container class for the server containing all methods that require server connectivity
 */

class Server : public QTcpServer
{
        Q_OBJECT
    public:

        /// Server Constructor
        Server(QObject *parent = 0);

	/**
        * @brief Starts the server with the parameters passed in. Returns bool if successful or not
	*
        * @param addr The host address we want to start the server at
        * @param port The port we want to start server from
	*/

        bool startServer(QHostAddress addr, quint16 port);

    protected:

	/**
        * @brief Implements incomingConnection(handle) method in QTcpServer to handle any incoming connections
	*
        * @param handle The function gets called internally and the handle of the socket is passed
	*/

        void incomingConnection(int handle);

    public slots:
	/**
        * @brief Slot that gets called whenever there is incoming data from any socket to the server
	*/

        void handleIncomingData();

	/**
        * @brief Slot that gets called whenever a client disconnects from the server
	*/

        void handleDisconnection();

    signals:
        /**
        * @brief Signal sent to remove friend
        * @param personSendingRequest The person sending the remove friend request
        * @param isValidRequest Boolean value to determine if the request is valid
        */

	void removeFriend(clientInformation* personSendingRequest, bool isValidRequest);

        /**
        * @brief Signal to check if the remove request was valid
        * @param personToRemove The person the user wishes to remove
        * @param isValidRequest Boolean value to determine if the request is valid
        */

	void sendIsValidRemoveFriendRequest(QString personToRemove, bool isValidRequest);

        /**
        * @brief Signal sent to add a friend
        * @param personSendingRequest The person sending the add friend request
        */

	void addFriend(QString personSendingRequest);

        /**
        * @brief Signal sent to check if the friend request was valid or not
        * @param personToAdd The person so add to the friends list
        * @param isValid Boolean value to determine if the request is valid
        */

	void sendIsValidFriendRequest(QString personToAdd, bool isValid);

        /**
        * @brief Signal sent to confirm friend request
        * @param sentUser The user the request was sent to
        * @param isAccepted Boolean value to determine if the friend request is accepted
        */

	void confirmFriendRequest(clientInformation* sentUser, bool isAccepted);

        /**
        * @brief Signal to send message
        * @param fromUser The from user
        * @param toUser The to user
        * @param message The message being sent
        * @param timeSentAt The time the message was sent
        */

	void sendMessage(QString fromUser, QString toUser, QString message, QString timeSentAt);

    private:
        /**
        * @brief Method to check if the username sent was valid or not...deciding on whether or not to use
        */

	void handleIsValidUserName(QTcpSocket* personThatSentData, QString nameOfUser, bool isValidUsername);

        /**
        * @brief Method to handle an incoming friend add request, Parameters are self-explanatory
        */

	void handleIncomingFriendRequest(QString personSendingRequest, QString personRecievingRequest, bool isValid);

        /**
        * @brief Method to handle an incoming friend remove request, Parameters are self-explanatory
        */

	void handleIncomingRemoveFriendRequest(QString personSendingRequest, QString personToRemove);

        /**
        * @brief Iterates over the users connected and sends out the updated users connected
        * Called whenever someone connects or disconnects
        */

	void updateUsers();

        /**
        * @brief Called when a user logs in and there are any requests to satisfy
        * @param The user that just logged on and we're checking if they have any pending requests
        */

	void satisfyAnyRequests(clientInformation* user);

	/**
        * @brief Hashtable that contains the socket as the key and the username that's linked to the socket as the value
	*/

	QHash<QTcpSocket* , QString> userSocketStringTable;

	/**
        * @brief Hashtable that contains the username as the key and the socket as the value
	*/

	QHash<QString, clientInformation*> userStringClientInformationTable;

	/**
        * @brief Table to store the friends lists of all the users that at one point have connected
	*/

	QHash<QString, clientInformation*> overallUsers;

	/**
        * @brief Stores the requests from and to the friend requests
	*/

	QHash<clientInformation*, clientInformation*> currentFriendRequests;

};

#endif // SERVER_H
